﻿// -------------------------------------------------------------------------
//    @FileName         :    ServicePackageTest.cpp
//    @Author           :    gaoyi
//    @Date             :    2025/1/20
//    @Email            :    445267987@qq.com
//    @Module           :    ServicePackageTest
//
// -------------------------------------------------------------------------

#include "BagSystemTestBase.h"
#include "MockItemDesc.h"

/**
 * @brief 背包服务测试类
 * 
 * 测试NFServicePackage的高级API功能：
 * - 便捷的物品添加和删除接口
 * - 金钱管理功能
 * - 批量物品操作
 * - 背包状态查询
 * - 各种实用工具方法
 */
class ServicePackageTest : public BagSystemTestBase {
protected:
    void SetUp() override {
        BagSystemTestBase::SetUp();
        
        // 创建测试玩家
        m_testPlayer = CreateTestPlayer();
        
        // 初始化玩家背包
        // 这里可以添加必要的背包初始化逻辑
    }
    
    void TearDown() override {
        m_testPlayer = nullptr;
        BagSystemTestBase::TearDown();
    }

protected:
    NFPlayer* m_testPlayer;
};

// === 物品操作测试 ===

/**
 * @brief 测试通过物品ID和数量添加物品
 */
TEST_F(ServicePackageTest, AddByItemIDAndNumTest) {
    // 添加普通物品
    int result1 = NFServicePackage::AddByItemIDAndNum(
        m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::NORMAL_ITEM_1, 1);
    ASSERT_EQ(result1, 0) << "添加普通物品失败";
    
    // 添加堆叠物品
    int result2 = NFServicePackage::AddByItemIDAndNum(
        m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::STACKABLE_ARROW, 100);
    ASSERT_EQ(result2, 0) << "添加堆叠物品失败";
    
    // 添加装备
    int result3 = NFServicePackage::AddByItemIDAndNum(
        m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::WEAPON_SWORD, 1);
    ASSERT_EQ(result3, 0) << "添加装备失败";
    
    // 验证物品数量
    int totalCount1 = 0, totalCount2 = 0, totalCount3 = 0;
    NFServicePackage::GetBagItemTotalNumByItemID(m_testPlayer, TestItemIds::NORMAL_ITEM_1, totalCount1);
    NFServicePackage::GetBagItemTotalNumByItemID(m_testPlayer, TestItemIds::STACKABLE_ARROW, totalCount2);
    NFServicePackage::GetBagItemTotalNumByItemID(m_testPlayer, TestItemIds::WEAPON_SWORD, totalCount3);
    
    ASSERT_EQ(totalCount1, 1) << "普通物品数量不正确";
    ASSERT_EQ(totalCount2, 100) << "堆叠物品数量不正确";
    ASSERT_EQ(totalCount3, 1) << "装备数量不正确";
}

/**
 * @brief 测试指定背包类型添加物品
 */
TEST_F(ServicePackageTest, AddToSpecificBagTypeTest) {
    // 添加到普通背包
    int result1 = NFServicePackage::AddByItemIDAndNum(
        m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::NORMAL_ITEM_1, 1, TEST_BAG_TYPE_NORMAL);
    ASSERT_EQ(result1, 0) << "添加到普通背包失败";
    
    // 添加到装备背包
    int result2 = NFServicePackage::AddByItemIDAndNum(
        m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::WEAPON_SWORD, 1, TEST_BAG_TYPE_EQUIP);
    ASSERT_EQ(result2, 0) << "添加到装备背包失败";
    
    // 添加到材料背包
    int result3 = NFServicePackage::AddByItemIDAndNum(
        m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::MATERIAL_WOOD, 50, TEST_BAG_TYPE_MATERIAL);
    ASSERT_EQ(result3, 0) << "添加到材料背包失败";
    
    // 验证物品在正确的背包中
    NFBagPage* normalBag = NFServicePackage::GetBagPage(m_testPlayer, TEST_BAG_TYPE_NORMAL);
    NFBagPage* equipBag = NFServicePackage::GetBagPage(m_testPlayer, TEST_BAG_TYPE_EQUIP);
    NFBagPage* materialBag = NFServicePackage::GetBagPage(m_testPlayer, TEST_BAG_TYPE_MATERIAL);
    
    ASSERT_NE(normalBag, nullptr) << "普通背包获取失败";
    ASSERT_NE(equipBag, nullptr) << "装备背包获取失败";
    ASSERT_NE(materialBag, nullptr) << "材料背包获取失败";
    
    ASSERT_TRUE(VerifyItemInBag(normalBag, TestItemIds::NORMAL_ITEM_1, 1)) << "普通背包物品验证失败";
    ASSERT_TRUE(VerifyItemInBag(equipBag, TestItemIds::WEAPON_SWORD, 1)) << "装备背包物品验证失败";
    ASSERT_TRUE(VerifyItemInBag(materialBag, TestItemIds::MATERIAL_WOOD, 50)) << "材料背包物品验证失败";
}

/**
 * @brief 测试批量添加物品
 */
TEST_F(ServicePackageTest, AddMultipleItemsTest) {
    // 准备物品列表
    std::vector<Item> items;
    for (int i = 0; i < 5; ++i) {
        Item item;
        item.set_id(TestItemIds::NORMAL_ITEM_1 + i);
        item.set_count(1);
        item.set_quality(TestQuality::WHITE);
        item.set_bind(false);
        items.push_back(item);
    }
    
    // 批量添加物品
    int result = NFServicePackage::AddItems(m_testPlayer, items, TEST_REASON_SYSTEM);
    ASSERT_EQ(result, items.size()) << "批量添加物品失败";
    
    // 验证所有物品都已添加
    for (const auto& item : items) {
        int totalCount = 0;
        NFServicePackage::GetBagItemTotalNumByItemID(m_testPlayer, item.id(), totalCount);
        ASSERT_EQ(totalCount, item.count()) << "物品" << item.id() << "数量不正确";
    }
}

/**
 * @brief 测试删除物品
 */
TEST_F(ServicePackageTest, DeleteItemsTest) {
    // 先添加一些物品
    NFServicePackage::AddByItemIDAndNum(m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::STACKABLE_ARROW, 200);
    NFServicePackage::AddByItemIDAndNum(m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::NORMAL_ITEM_1, 5);
    
    // 部分删除堆叠物品
    int deletedCount1 = 0;
    int result1 = NFServicePackage::DelItemByItemIDAndNum(
        m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::STACKABLE_ARROW, 80, &deletedCount1);
    ASSERT_EQ(result1, 0) << "删除堆叠物品失败";
    ASSERT_EQ(deletedCount1, 80) << "删除数量不正确";
    
    // 验证剩余数量
    int remainingCount1 = 0;
    NFServicePackage::GetBagItemTotalNumByItemID(m_testPlayer, TestItemIds::STACKABLE_ARROW, remainingCount1);
    ASSERT_EQ(remainingCount1, 120) << "堆叠物品剩余数量不正确";
    
    // 完全删除普通物品
    int result2 = NFServicePackage::DelAllItemByItemID(m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::NORMAL_ITEM_1);
    ASSERT_EQ(result2, 0) << "删除所有普通物品失败";
    
    // 验证物品已完全删除
    int remainingCount2 = 0;
    NFServicePackage::GetBagItemTotalNumByItemID(m_testPlayer, TestItemIds::NORMAL_ITEM_1, remainingCount2);
    ASSERT_EQ(remainingCount2, 0) << "普通物品应该已完全删除";
}

/**
 * @brief 测试按格子删除物品
 */
TEST_F(ServicePackageTest, DeleteByGridTest) {
    // 添加物品
    NFServicePackage::AddByItemIDAndNum(m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::NORMAL_ITEM_1, 1);
    NFServicePackage::AddByItemIDAndNum(m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::STACKABLE_ARROW, 100);
    
    // 获取背包
    NFBagPage* bagPage = NFServicePackage::GetBagPage(m_testPlayer, TEST_BAG_TYPE_NORMAL);
    ASSERT_NE(bagPage, nullptr) << "获取背包失败";
    
    // 删除第一个格子的物品
    int result1 = NFServicePackage::DelItemByGrid(m_testPlayer, TEST_REASON_SYSTEM, 0);
    ASSERT_EQ(result1, 0) << "按格子删除物品失败";
    
    // 部分删除第二个格子的物品
    int result2 = NFServicePackage::DelItemByNumWithGrid(m_testPlayer, TEST_REASON_SYSTEM, 1, 30);
    ASSERT_EQ(result2, 0) << "按格子部分删除物品失败";
    
    // 验证删除结果
    int remainingCount1 = 0, remainingCount2 = 0;
    NFServicePackage::GetBagItemTotalNumByItemID(m_testPlayer, TestItemIds::NORMAL_ITEM_1, remainingCount1);
    NFServicePackage::GetBagItemTotalNumByItemID(m_testPlayer, TestItemIds::STACKABLE_ARROW, remainingCount2);
    
    ASSERT_EQ(remainingCount1, 0) << "第一个物品应该已删除";
    ASSERT_EQ(remainingCount2, 70) << "第二个物品应该剩余70个";
}

// === 金钱管理测试 ===

/**
 * @brief 测试金钱获取和设置
 */
TEST_F(ServicePackageTest, MoneyManagementTest) {
    // 测试初始金钱
    int64_t initialGold = NFServicePackage::GetMoneyNumber(m_testPlayer, TEST_MONEY_TYPE_GOLD);
    int64_t initialSilver = NFServicePackage::GetMoneyNumber(m_testPlayer, TEST_MONEY_TYPE_SILVER);
    int64_t initialDiamond = NFServicePackage::GetMoneyNumber(m_testPlayer, TEST_MONEY_TYPE_DIAMOND);
    
    // 设置金钱
    int result1 = NFServicePackage::SetMoneyNumber(m_testPlayer, TEST_MONEY_TYPE_GOLD, 1000);
    ASSERT_EQ(result1, 0) << "设置金币失败";
    
    int result2 = NFServicePackage::SetMoneyNumber(m_testPlayer, TEST_MONEY_TYPE_SILVER, 500);
    ASSERT_EQ(result2, 0) << "设置银币失败";
    
    int result3 = NFServicePackage::SetMoneyNumber(m_testPlayer, TEST_MONEY_TYPE_DIAMOND, 100);
    ASSERT_EQ(result3, 0) << "设置钻石失败";
    
    // 验证金钱设置
    VerifyMoneyAmount(m_testPlayer, TEST_MONEY_TYPE_GOLD, 1000);
    VerifyMoneyAmount(m_testPlayer, TEST_MONEY_TYPE_SILVER, 500);
    VerifyMoneyAmount(m_testPlayer, TEST_MONEY_TYPE_DIAMOND, 100);
    
    // 获取金钱对象
    Money* goldMoney = NFServicePackage::GetMoney(m_testPlayer, TEST_MONEY_TYPE_GOLD);
    Money* silverMoney = NFServicePackage::GetMoney(m_testPlayer, TEST_MONEY_TYPE_SILVER);
    Money* diamondMoney = NFServicePackage::GetMoney(m_testPlayer, TEST_MONEY_TYPE_DIAMOND);
    
    ASSERT_NE(goldMoney, nullptr) << "金币对象获取失败";
    ASSERT_NE(silverMoney, nullptr) << "银币对象获取失败";
    ASSERT_NE(diamondMoney, nullptr) << "钻石对象获取失败";
}

// === 查询功能测试 ===

/**
 * @brief 测试物品数量查询
 */
TEST_F(ServicePackageTest, ItemCountQueryTest) {
    // 添加不同数量的物品
    NFServicePackage::AddByItemIDAndNum(m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::NORMAL_ITEM_1, 1);
    NFServicePackage::AddByItemIDAndNum(m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::STACKABLE_ARROW, 150);
    NFServicePackage::AddByItemIDAndNum(m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::WEAPON_SWORD, 1);
    
    // 查询总数量
    int totalCount1 = NFServicePackage::GetItemTotalNum(m_testPlayer, TestItemIds::NORMAL_ITEM_1);
    int totalCount2 = NFServicePackage::GetItemTotalNum(m_testPlayer, TestItemIds::STACKABLE_ARROW);
    int totalCount3 = NFServicePackage::GetItemTotalNum(m_testPlayer, TestItemIds::WEAPON_SWORD);
    int totalCount4 = NFServicePackage::GetItemTotalNum(m_testPlayer, TestItemIds::POTION_HP);
    
    ASSERT_EQ(totalCount1, 1) << "普通物品数量查询错误";
    ASSERT_EQ(totalCount2, 150) << "堆叠物品数量查询错误";
    ASSERT_EQ(totalCount3, 1) << "装备数量查询错误";
    ASSERT_EQ(totalCount4, 0) << "不存在物品数量应该为0";
    
    // 使用引用参数查询
    int refCount1 = 0, refCount2 = 0;
    int result1 = NFServicePackage::GetItemTotalNum(m_testPlayer, TestItemIds::NORMAL_ITEM_1, refCount1);
    int result2 = NFServicePackage::GetItemTotalNum(m_testPlayer, TestItemIds::STACKABLE_ARROW, refCount2);
    
    ASSERT_EQ(result1, 0) << "引用参数查询失败";
    ASSERT_EQ(result2, 0) << "引用参数查询失败";
    ASSERT_EQ(refCount1, 1) << "引用参数查询结果错误";
    ASSERT_EQ(refCount2, 150) << "引用参数查询结果错误";
}

/**
 * @brief 测试物品获取功能
 */
TEST_F(ServicePackageTest, GetItemTest) {
    // 添加测试物品
    NFServicePackage::AddByItemIDAndNum(m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::WEAPON_SWORD, 1);
    NFServicePackage::AddByItemIDAndNum(m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::STACKABLE_ARROW, 100);
    
    // 按背包类型和格子索引获取物品
    NFGridItem item1;
    int result1 = NFServicePackage::GetItem(m_testPlayer, TEST_BAG_TYPE_NORMAL, 0, &item1);
    ASSERT_EQ(result1, 0) << "按格子索引获取物品失败";
    ASSERT_FALSE(item1.IsEmpty()) << "获取的物品不应该为空";
    
    // 按物品ID获取物品
    NFGridItem item2;
    int result2 = NFServicePackage::GetItemByItemID(m_testPlayer, TEST_BAG_TYPE_NORMAL, TestItemIds::STACKABLE_ARROW, &item2);
    ASSERT_EQ(result2, 0) << "按物品ID获取物品失败";
    ASSERT_EQ(item2.GetItemID(), TestItemIds::STACKABLE_ARROW) << "获取的物品ID不正确";
    ASSERT_EQ(item2.GetNumber(), 100) << "获取的物品数量不正确";
    
    // 按UUID获取物品
    uint64_t uuid = item1.GetUUID();
    NFGridItem item3;
    int result3 = NFServicePackage::GetItemByUUID(m_testPlayer, TEST_BAG_TYPE_NORMAL, uuid, &item3);
    ASSERT_EQ(result3, 0) << "按UUID获取物品失败";
    ASSERT_EQ(item3.GetUUID(), uuid) << "获取的物品UUID不正确";
}

/**
 * @brief 测试获取背包中所有物品
 */
TEST_F(ServicePackageTest, GetAllItemsInBagTest) {
    // 添加多个物品
    for (int i = 0; i < 5; ++i) {
        NFServicePackage::AddByItemIDAndNum(m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::NORMAL_ITEM_1 + i, 1);
    }
    
    // 获取背包中所有物品
    std::vector<NFGridItem> allItems;
    int result = NFServicePackage::GetItem(m_testPlayer, TEST_BAG_TYPE_NORMAL, allItems);
    ASSERT_EQ(result, 0) << "获取背包所有物品失败";
    
    // 验证获取的物品数量
    int nonEmptyCount = 0;
    for (const auto& item : allItems) {
        if (!item.IsEmpty()) {
            nonEmptyCount++;
        }
    }
    ASSERT_EQ(nonEmptyCount, 5) << "获取的非空物品数量不正确";
}

// === 边界和异常测试 ===

/**
 * @brief 测试空指针参数处理
 */
TEST_F(ServicePackageTest, NullPointerTest) {
    // 测试空玩家指针
    int result1 = NFServicePackage::AddByItemIDAndNum(nullptr, TEST_REASON_SYSTEM, TestItemIds::NORMAL_ITEM_1, 1);
    ASSERT_NE(result1, 0) << "空玩家指针应该返回错误";
    
    int64_t money = NFServicePackage::GetMoneyNumber(nullptr, TEST_MONEY_TYPE_GOLD);
    ASSERT_EQ(money, 0) << "空玩家指针获取金钱应该返回0";
    
    Money* moneyPtr = NFServicePackage::GetMoney(nullptr, TEST_MONEY_TYPE_GOLD);
    ASSERT_EQ(moneyPtr, nullptr) << "空玩家指针获取金钱对象应该返回nullptr";
    
    NFBagPage* bagPage = NFServicePackage::GetBagPage(nullptr, TEST_BAG_TYPE_NORMAL);
    ASSERT_EQ(bagPage, nullptr) << "空玩家指针获取背包应该返回nullptr";
}

/**
 * @brief 测试无效参数处理
 */
TEST_F(ServicePackageTest, InvalidParameterTest) {
    // 测试无效物品ID
    int result1 = NFServicePackage::AddByItemIDAndNum(m_testPlayer, TEST_REASON_SYSTEM, -1, 1);
    ASSERT_NE(result1, 0) << "无效物品ID应该返回错误";
    
    // 测试无效数量
    int result2 = NFServicePackage::AddByItemIDAndNum(m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::NORMAL_ITEM_1, 0);
    ASSERT_NE(result2, 0) << "无效数量应该返回错误";
    
    int result3 = NFServicePackage::AddByItemIDAndNum(m_testPlayer, TEST_REASON_SYSTEM, TestItemIds::NORMAL_ITEM_1, -1);
    ASSERT_NE(result3, 0) << "负数量应该返回错误";
    
    // 测试无效背包类型
    NFBagPage* bagPage = NFServicePackage::GetBagPage(m_testPlayer, -1);
    ASSERT_EQ(bagPage, nullptr) << "无效背包类型应该返回nullptr";
    
    // 测试无效金钱类型
    int64_t money = NFServicePackage::GetMoneyNumber(m_testPlayer, -1);
    ASSERT_EQ(money, 0) << "无效金钱类型应该返回0";
} 